"use strict";
import min2phase from "./min2phase";

function cube(cs,es){
	var cornerS = cs;
	var edgeS = es;
	var corner = Array.from(cs);
	var edge = Array.from(es);
	
	var bufferIndex_C = 1;//角缓冲块位置
	var bufferIndex_E = 2;//棱缓冲块位置
	var cornerIsKeep = true;
	var edgeIsKeep = true;
	var cornerLend = [0,1,2,3,5,4,7,6];
	var edgeLend = [1,3,0,2,7,9,11,5,15,16,13,14];
	
	var cornerCodeArray = [];
	var cornerCodeFlipArray = [];
	var edgeCodeArray = [];
	var edgeCodeFlipArray = [];
	
	this.initRead = function(bufferC,bufferE,isKeepC,isKeepE,lendC,lendE){
		bufferIndex_C = bufferC;
		bufferIndex_E = bufferE;
		cornerIsKeep = isKeepC;
		edgeIsKeep = isKeepE;
		cornerLend = Array.from(lendC);
		edgeLend = Array.from(lendE);
	}
	
	this.initBuffer = function(bufferC,bufferE){
		bufferIndex_C = bufferC;
		bufferIndex_E = bufferE;
	}
	
	this.rotateR = function(){
		var c_source0 = corner[0];
		corner[0] = corner[1][2]+corner[1][0]+corner[1][1];
		corner[1] = corner[5][1]+corner[5][2]+corner[5][0];
		corner[5] = corner[4][2]+corner[4][0]+corner[4][1];
		corner[4] = c_source0[1]+c_source0[2]+c_source0[0];
		
		var e_source1 = edge[1];
		edge[1]=edge[7];
		edge[7]=edge[14];
		edge[14]=edge[5];
		edge[5]=e_source1;
	};
	
	this.rotateU = function(){
		var c_source0 = corner[0];
		corner[0] = corner[3];
		corner[3] = corner[2];
		corner[2] = corner[1];
		corner[1] = c_source0;
		
		var e_source0 = edge[0];
		edge[0] = edge[3];
		edge[3] = edge[2];
		edge[2] = edge[1];
		edge[1] = e_source0;
		
	};
	
	this.rotateF = function(){
		var c_source1 = corner[1];
		corner[1] = corner[2][2]+corner[2][0]+corner[2][1];
		corner[2] = corner[6][1]+corner[6][2]+corner[6][0];
		corner[6] = corner[5][2]+corner[5][0]+corner[5][1];
		corner[5] = c_source1[1]+c_source1[2]+c_source1[0];
		
		var e_source2 = edge[2];
		edge[2] = edge[9][1]+edge[9][0];
		edge[9] = edge[15][1]+edge[15][0];
		edge[15] = edge[7][1]+edge[7][0];
		edge[7] = e_source2[1]+e_source2[0];
		
	};
	
	this.rotateL = function(){
		var c_source2 = corner[2];
		corner[2] = corner[3][2]+corner[3][0]+corner[3][1];
		corner[3] = corner[7][1]+corner[7][2]+corner[7][0];
		corner[7] = corner[6][2]+corner[6][0]+corner[6][1];
		corner[6] = c_source2[1]+c_source2[2]+c_source2[0];
		
		var e_source3 = edge[3];
		edge[3] = edge[11];
		edge[11] = edge[16];
		edge[16] = edge[9];
		edge[9] = e_source3;
		
	};
	
	this.rotateD = function(){
		var c_source4 = corner[4];
		corner[4] = corner[5];
		corner[5] = corner[6];
		corner[6] = corner[7];
		corner[7] = c_source4;
		
		var e_source13 = edge[13];
		edge[13] = edge[14];
		edge[14] = edge[15];
		edge[15] = edge[16];
		edge[16] = e_source13;
		
	};
	
	this.rotateB = function(){
		var c_source0 = corner[0];
		corner[0] = corner[4][1]+corner[4][2]+corner[4][0];
		corner[4] = corner[7][2]+corner[7][0]+corner[7][1];
		corner[7] = corner[3][1]+corner[3][2]+corner[3][0];
		corner[3] = c_source0[2]+c_source0[0]+c_source0[1];
		
		var e_source0 = edge[0];
		edge[0] = edge[5][1]+edge[5][0];
		edge[5] = edge[13][1]+edge[13][0];
		edge[13] = edge[11][1]+edge[11][0];
		edge[11] = e_source0[1]+e_source0[0];
		
	};
	
	
	this.rotateE = function(){
		
		var e_source5 = edge[5];
		edge[5] = edge[7][1]+edge[7][0];
		edge[7] = edge[9][1]+edge[9][0];
		edge[9] = edge[11][1]+edge[11][0];
		edge[11] = e_source5[1]+e_source5[0];
		
		var e_sourceRR = edge[6];
		edge[6] = edge[8];
		edge[8] = edge[10];
		edge[10] = edge[12];
		edge[12] = e_sourceRR;
		
	};
	
	this.rotateM = function(){
		
		var e_source0 = edge[0];
		edge[0] = edge[13][1]+edge[13][0];
		edge[13] = edge[15][1]+edge[15][0];
		edge[15] = edge[2][1]+edge[2][0];
		edge[2] = e_source0[1]+e_source0[0];
		
		var e_sourceUU = edge[4];
		edge[4] = edge[12];
		edge[12] = edge[17];
		edge[17] = edge[8];
		edge[8] = e_sourceUU;
		
	};
	
	this.rotateS = function(){
		var e_source1 = edge[1];
		edge[1] = edge[3][1]+edge[3][0];
		edge[3] = edge[16][1]+edge[16][0];
		edge[16] = edge[14][1]+edge[14][0];
		edge[14] = e_source1[1]+e_source1[0];
		
		var e_sourceUU = edge[4];
		edge[4] = edge[10];
		edge[10] = edge[17];
		edge[17] = edge[6];
		edge[6] = e_sourceUU;
		
	};
	
	this.disrupt = function(e){
		for(var i=0;i<e.length;i++){
			var c = e[i];
			switch(c){
				case "R":
					this.rotateR();
				break;
				case "R'":
					this.rotateR();
					this.rotateR();
					this.rotateR();
				break;
				case "R2":
					this.rotateR();
					this.rotateR();
				break;
				case "U":
					this.rotateU();
				break;
				case "U'":
					this.rotateU();
					this.rotateU();
					this.rotateU();
				break;
				case "U2":
					this.rotateU();
					this.rotateU();
				break;
				case "D":
					this.rotateD();
				break;
				case "D'":
					this.rotateD();
					this.rotateD();
					this.rotateD();
				break;
				case "D2":
					this.rotateD();
					this.rotateD();
				break;
				case "L":
					this.rotateL();
				break;
				case "L'":
					this.rotateL();
					this.rotateL();
					this.rotateL();
				break;
				case "L2":
					this.rotateL();
					this.rotateL();
				break;
				case "B":
					this.rotateB();
				break;
				case "B'":
					this.rotateB();
					this.rotateB();
					this.rotateB();
				break;
				case "B2":
					this.rotateB();
					this.rotateB();
				break;
				case "F":
					this.rotateF();
				break;
				case "F'":
					this.rotateF();
					this.rotateF();
					this.rotateF();
				break;
				case "F2":
					this.rotateF();
					this.rotateF();
				break;
				case "Rw":
					this.rotateR();
					this.rotateM();
					this.rotateM();
					this.rotateM();
				break;
				case "Rw'":
					this.rotateR();
					this.rotateR();
					this.rotateR();
					this.rotateM();
				break;
				case "Rw2":
					this.rotateR();
					this.rotateR();
					this.rotateM();
					this.rotateM();
				break;
				case "Fw":
					this.rotateF();
					this.rotateS();
				break;
				case "Fw'":
					this.rotateF();
					this.rotateF();
					this.rotateF();
					this.rotateS();
					this.rotateS();
					this.rotateS();
				break;
				case "Fw2":
					this.rotateF();
					this.rotateF();
					this.rotateS();
					this.rotateS();
				break;
				case "Uw":
					this.rotateU();
					this.rotateE();
					this.rotateE();
					this.rotateE();
				break;
				case "Uw'":
					this.rotateU();
					this.rotateU();
					this.rotateU();
					this.rotateE();
				break;
				case "Uw2":
					this.rotateU();
					this.rotateU();
					this.rotateE();
					this.rotateE();
				break;
				case "Fw2":
					this.rotateF();
					this.rotateF();
					this.rotateS();
					this.rotateS();
				break;
				case "x":
					this.rotateR();
					this.rotateM();
					this.rotateM();
					this.rotateM();
					this.rotateL();
					this.rotateL();
					this.rotateL();
				break;
				case "x'":
					this.rotateR();
					this.rotateR();
					this.rotateR();
					this.rotateM();
					this.rotateL();
				break;
				case "x2":
					this.rotateR();
					this.rotateR();
					this.rotateM();
					this.rotateM();
					this.rotateL();
					this.rotateL();
				break;
				case "y":
					this.rotateU();
					this.rotateE();
					this.rotateE();
					this.rotateE();
					this.rotateD();
					this.rotateD();
					this.rotateD();
				break;
				case "y'":
					this.rotateU();
					this.rotateU();
					this.rotateU();
					this.rotateE();
					this.rotateD();
				break;
				case "y2":
					this.rotateU();
					this.rotateU();
					this.rotateE();
					this.rotateE();
					this.rotateD();
					this.rotateD();
				break;
				case "z":
					this.rotateB();
					this.rotateB();
					this.rotateB();
					this.rotateS();
					this.rotateF();
				break;
				case "z'":
					this.rotateB();
					this.rotateS();
					this.rotateS();
					this.rotateS();
					this.rotateF();
					this.rotateF();
					this.rotateF();
				break;
				case "z2":
					this.rotateB();
					this.rotateB();
					this.rotateS();
					this.rotateS();
					this.rotateF();
					this.rotateF();
				break;
				case "Bw":
					this.rotateB();
					this.rotateS();
					this.rotateS();
					this.rotateS();
				break;
				case "Bw'":
					this.rotateB();
					this.rotateB();
					this.rotateB();
					this.rotateS();
				break;
				case "Bw2":
					this.rotateB();
					this.rotateB();
					this.rotateS();
					this.rotateS();
				break;
				case "Lw":
					this.rotateL();
					this.rotateM();
				break;
				case "Lw'":
					this.rotateL();
					this.rotateL();
					this.rotateL();
					this.rotateM();
					this.rotateM();
					this.rotateM();
				break;
				case "Lw2":
					this.rotateL();
					this.rotateL();
					this.rotateM();
					this.rotateM();
				break;
				case "Dw":
					this.rotateD();
					this.rotateE();
				break;
				case "Dw'":
					this.rotateD();
					this.rotateD();
					this.rotateD();
					this.rotateE();
					this.rotateE();
					this.rotateE();
				break;
				case "Dw2":
					this.rotateD();
					this.rotateD();
					this.rotateE();
					this.rotateE();
				break;
			}
		}
		
		
	}
	
	this.getState = function(){
		var state = [];
		state = [this.getFactC(corner[3][0]), this.getFactE(edge[0][0]),this.getFactC(corner[0][0]),
				this.getFactE(edge[3][0]), edge[4][0],  this.getFactE(edge[1][0]),
				this.getFactC(corner[2][0]), this.getFactE(edge[2][0]),this.getFactC(corner[1][0]),
				
				this.getFactC(corner[1][1]), this.getFactE(edge[1][1]),this.getFactC(corner[0][2]),
				this.getFactE(edge[7][1]), edge[6][0],  this.getFactE(edge[5][1]),
				this.getFactC(corner[5][2]), this.getFactE(edge[14][1]),this.getFactC(corner[4][1]),
		
				this.getFactC(corner[2][1]), this.getFactE(edge[2][1]),this.getFactC(corner[1][2]),
				this.getFactE(edge[9][0]), edge[8][0],  this.getFactE(edge[7][0]),
				this.getFactC(corner[6][2]), this.getFactE(edge[15][1]),this.getFactC(corner[5][1]),
				
				
				this.getFactC(corner[6][0]), this.getFactE(edge[15][0]),this.getFactC(corner[5][0]),
				this.getFactE(edge[16][0]), edge[17][0],  this.getFactE(edge[14][0]),
				this.getFactC(corner[7][0]), this.getFactE(edge[13][0]),this.getFactC(corner[4][0]),
				
				
				this.getFactC(corner[3][1]), this.getFactE(edge[3][1]),this.getFactC(corner[2][2]),
				this.getFactE(edge[11][1]), edge[10][0],  this.getFactE(edge[9][1]),
				this.getFactC(corner[7][2]), this.getFactE(edge[16][1]),this.getFactC(corner[6][1]),
						
				this.getFactC(corner[0][1]), this.getFactE(edge[0][1]),this.getFactC(corner[3][2]),
				this.getFactE(edge[5][0]), edge[12][0],  this.getFactE(edge[11][0]),
				this.getFactC(corner[4][2]), this.getFactE(edge[13][1]),this.getFactC(corner[7][1]),
		];
		return state;
	}
	
	this.getFactC = function(e){
		
		if(cornerS[0][0]==e)return "U";
		if(cornerS[0][1]==e)return "B";
		if(cornerS[0][2]==e)return "R";
		
		if(cornerS[1][0]==e)return "U";
		if(cornerS[1][1]==e)return "R";
		if(cornerS[1][2]==e)return "F";
		
		if(cornerS[2][0]==e)return "U";
		if(cornerS[2][1]==e)return "F";
		if(cornerS[2][2]==e)return "L";
		
		if(cornerS[3][0]==e)return "U";
		if(cornerS[3][1]==e)return "L";
		if(cornerS[3][2]==e)return "B";
		
		if(cornerS[4][0]==e)return "D";
		if(cornerS[4][1]==e)return "R";
		if(cornerS[4][2]==e)return "B";
		
		if(cornerS[5][0]==e)return "D";
		if(cornerS[5][1]==e)return "F";
		if(cornerS[5][2]==e)return "R";
		
		if(cornerS[6][0]==e)return "D";
		if(cornerS[6][1]==e)return "L";
		if(cornerS[6][2]==e)return "F";
		
		if(cornerS[7][0]==e)return "D";
		if(cornerS[7][1]==e)return "B";
		if(cornerS[7][2]==e)return "L";
		
	}
	
	
	this.getFactE = function(e){
		if(edgeS[0][0]==e)return "U";
		if(edgeS[0][1]==e)return "B";
		
		if(edgeS[1][0]==e)return "U";
		if(edgeS[1][1]==e)return "R";
		
		if(edgeS[2][0]==e)return "U";
		if(edgeS[2][1]==e)return "F";
		
		if(edgeS[3][0]==e)return "U";
		if(edgeS[3][1]==e)return "L";
		
		if(edgeS[5][0]==e)return "B";
		if(edgeS[5][1]==e)return "R";
		
		if(edgeS[7][0]==e)return "F";
		if(edgeS[7][1]==e)return "R";
		
		if(edgeS[9][0]==e)return "F";
		if(edgeS[9][1]==e)return "L";
		
		if(edgeS[11][0]==e)return "B";
		if(edgeS[11][1]==e)return "L";
		
		if(edgeS[13][0]==e)return "D";
		if(edgeS[13][1]==e)return "B";
		
		if(edgeS[14][0]==e)return "D";
		if(edgeS[14][1]==e)return "R";
		
		if(edgeS[15][0]==e)return "D";
		if(edgeS[15][1]==e)return "F";
		
		if(edgeS[16][0]==e)return "D";
		if(edgeS[16][1]==e)return "L";
		
	}
	
	this.handlCoordinate = function(){
		
		var res = "";
		if(edge[4][0]=="U" && edge[8][0]=="F")return res;
		
		
		if(edge[17][0]=="U"){
			res+=" x2 ";
			this.rotateR();
			this.rotateR();
			this.rotateM();
			this.rotateM();
			this.rotateL();
			this.rotateL();
		}else if(edge[10][0]=="U"){
			res+=" z ";
			this.rotateF();
			this.rotateS();
			this.rotateB();
			this.rotateB();
			this.rotateB();
		}else if(edge[6][0]=="U"){
			res+=" z' ";
			this.rotateB();
			this.rotateS();
			this.rotateS();
			this.rotateS();
			this.rotateF();
			this.rotateF();
			this.rotateF();
		}else if(edge[8][0]=="U"){
			res+=" x ";
			this.rotateR();
			this.rotateM();
			this.rotateM();
			this.rotateM();
			this.rotateL();
			this.rotateL();
			this.rotateL();
			
		}else if(edge[12][0]=="U"){
			res+=" x' ";
			this.rotateM();
			this.rotateL();
			this.rotateR();
			this.rotateR();
			this.rotateR();
		}
		
		
		if(edge[10][0]=="F"){
			res+="y'";
			this.rotateU();
			this.rotateU();
			this.rotateU();
			this.rotateE();
			this.rotateD();
		}else if(edge[6][0]=="F"){
			res+="y";
			this.rotateU();
			this.rotateE();
			this.rotateE();
			this.rotateE();
			this.rotateD();
			this.rotateD();
			this.rotateD();
			
		}else if(edge[12][0]=="F"){
			res+="y2";
			this.rotateU();
			this.rotateU();
			this.rotateE();
			this.rotateE();
			this.rotateD();
			this.rotateD();
		}
		
		return res;
		
	}
	
	
	
	
	this.read = function(){
		//频繁读缓存，导致有时候读不到
		// bufferIndex_C = constant.getBufferIndex_C();
		// bufferIndex_E = constant.getBufferIndex_E();
		// cornerIsKeep = constant.getCornerIsKeep();
		// edgeIsKeep = constant.getEdgeIsKeep();
		// cornerLend = constant.getCornerLend();
		// edgeLend = constant.getEdgeLend();
		
		var coordinate = this.handlCoordinate();
		var res = [];//[坐标，角编码，角翻色，棱编码，棱翻色]
		res.push(coordinate);
		
		//先删除借位顺序里缓冲位置
		for(var i = 0;i<cornerLend.length;i++){
			if(bufferIndex_C==cornerLend[i]){
				cornerLend.splice(i,1);
				break;
			}
		}
		for(var i = 0;i<edgeLend.length;i++){
			if(bufferIndex_E==edgeLend[i]){
				edgeLend.splice(i,1);
				break;
			}
		}
		
		this.handReadCode(bufferIndex_C,0,-1);
		this.handReadEdgeCode(bufferIndex_E,0,-1);
		res.push(cornerCodeArray);
		res.push(cornerCodeFlipArray);
		res.push(edgeCodeArray);
		res.push(edgeCodeFlipArray);
		return res;
		
	}
	
	/*-----------角读码start-----------*/
	//根据编码 取源魔方该编码所在的位置
	this.getCornerS_index = function(code){
		var res = [];
		for(var i = 0;i<cornerS.length;i++){
			var s_3 = cornerS[i];
			for(var j = 0;j<s_3.length;j++){
				var c = s_3[j];
				if(code==c){
					res = [i,j];
					break;
				}
			}
		}
		
		return res;
	}
	//正常读码
	this.handReadCode = function(index,c,indexLend){
		var code2 = corner[index][c];
		var deleteIndex = cornerLend.indexOf(this.getCornerS_index(code2)[0]);
		if(deleteIndex!=-1){
			cornerLend.splice(deleteIndex,1);//编过的位置要在借位顺序里即时删除
		}
		var isHoming = false;
		var currentIndex = -1;
		
		var buffer_index = index;
		if(indexLend==-1){
			buffer_index = bufferIndex_C;
		}
		for(var c = 0;c<cornerS[index].length;c++){//是否归位
			currentIndex = c;
			if(code2==cornerS[buffer_index][c]){
				isHoming = true;
				break;
			}
			
		}
		
		if(isHoming){//归位，需借位
			var lend = this.getLendIndex();
			if(lend==-1)return;
			var jw = corner[lend];
			if(this.isHoming(jw,lend)){
				return;
			}
			this.handCodeLend(lend,currentIndex);
		}else{
			cornerCodeArray.push({"code":code2});
			var indexArray = this.getCornerS_index(code2);
			var code3 = corner[indexArray[0]][indexArray[1]];
			var indexArray2 =this.getCornerS_index(code3);
			
			if(indexArray2[0]==indexLend){//还位
				cornerCodeArray.push({"code":code3,"isH":true});
				//判断是否编完
				if(cornerLend.length!=0){
					//继续借位
					var lend = this.getLendIndex();
					if(lend==-1)return;
					var jw = corner[lend];
					if(this.isHoming(jw,lend)){
						return;
					}
					this.handCodeLend(lend,indexArray2[1]);
				}
			}else{
				this.handReadCode(indexArray[0],indexArray[1],indexLend);
			}
			
		}
		
	}
	//需要借位的时候取编码逻辑
	this.handCodeLend = function(indexLend,c){
		if(indexLend==-1){
			return;//借位顺序里的位置全部用完，默认读码结果
		}
		var code = "";
		var code2 = "";
		if(cornerIsKeep){//保持色向借位
			code = cornerS[indexLend][c];
			code2 = corner[indexLend][c];
		}else{
			code = cornerS[indexLend][0];
			code2 = corner[indexLend][0];
		}
		cornerCodeArray.push({"code":code,"isLend":true});
		cornerCodeArray.push({"code":code2});
		
		var deleteIndex = cornerLend.indexOf(this.getCornerS_index(code2)[0]);
		if(deleteIndex!=-1){
			cornerLend.splice(deleteIndex,1);//编过的位置要在借位顺序里即时删除
		}
		
		var indexArray = this.getCornerS_index(code2);
		var code3 = corner[indexArray[0]][indexArray[1]];
		var indexArray2 =this.getCornerS_index(code3);
		
		if(indexArray2[0]==indexLend){//还位
			cornerCodeArray.push({"code":code3,"isH":true});
			//判断是否编完
			if(cornerLend.length!=0){
				//继续借位
				indexLend = this.getLendIndex();
				if(indexLend==-1)return;
				var jw = corner[indexLend];
				if(this.isHoming(jw,indexLend)){
					return;
				}
				this.handCodeLend(indexLend,indexArray2[1]);
			}
		}else{
			this.handReadCode(indexArray[0],indexArray[1],indexLend);
			
		}
		
	}
	//取出可以借位的位置index
	this.getLendIndex = function(){
		var indexLend = -1;//当前所借的位置
		do{
			if(cornerLend.length==0){
				break;
			}
			indexLend = cornerLend.shift();//从借位顺序里取出第一个，并删除它
			//如果所借位置已归位，则重新取一个借位位置
			var jw = corner[indexLend];
			var is = this.isHoming(jw,indexLend);
			if(!is){
				break;
			}
		}while(cornerLend.length>0);
		
		return indexLend;
	}
	//用来判断当前位置是否已经归位
	this.isHoming = function(c,indexLend){
		var res = false;
		var s = cornerS[indexLend];
		if(c[0]==s[0]){
			//归位且色向正确
			return true;
		}else if(c[0]==s[1]){
			//不是缓冲块的归位，需要记录翻色情况 顺翻
			if(indexLend!=bufferIndex_C){
				var b = cornerCodeFlipArray.includes(s[2]+""+s[0]);
				if(!b){
					cornerCodeFlipArray.push(s[2]+""+s[0]);
				}
			}
			return true;
		}else if(c[0]==s[2]){
			//不是缓冲块的归位，需要记录翻色情况 逆翻
			if(indexLend!=bufferIndex_C){
				var b = cornerCodeFlipArray.includes(s[1]+""+s[0]);
				if(!b){
					cornerCodeFlipArray.push(s[1]+""+s[0]);
				}
				
			}
			return true;
		}
		
		return res;
	}
	/*-----------角读码end-----------*/


	/*-----------棱读码start-----------*/ 
	//根据编码 取源魔方该编码所在的位置
	this.getEdgeS_index = function(code){
		var res = [];
		for(var i = 0;i<edgeS.length;i++){
			var e_2 = edgeS[i];
			if(e_2[0]==e_2[1]){//处理中心块 UU FF BB ... 这些会混淆编码位置导致拿错index
				continue;
			}
			for(var j = 0;j<e_2.length;j++){
				var e = e_2[j];
				if(code==e){
					res = [i,j];
					break;
				}
			}
		}
		
		return res;
	}
	//正常读码
	this.handReadEdgeCode = function(index,c,indexLend){
		var code2 = edge[index][c];
		var deleteIndex = edgeLend.indexOf(this.getEdgeS_index(code2)[0]);
		if(deleteIndex!=-1){
			edgeLend.splice(deleteIndex,1);//编过的位置要在借位顺序里即时删除
		}
		var isHoming = false;
		var currentIndex = -1;
		
		var buffer_index = index;
		if(indexLend==-1){
			buffer_index = bufferIndex_E;
		}
		for(var c = 0;c<edgeS[index].length;c++){//是否归位
			currentIndex = c;
			if(code2==edgeS[buffer_index][c]){
				isHoming = true;
				break;
			}
			
		}
		
		if(isHoming){//归位，需借位
			var lend = this.getEdgeLendIndex();
			if(lend==-1)return;
			var jw = edge[lend];
			if(this.edgeIsHoming(jw,lend)){
				return;
			}
			this.handEdgeCodeLend(lend,currentIndex);
		}else{
			edgeCodeArray.push({"code":code2});
			var indexArray = this.getEdgeS_index(code2);
			var code3 = edge[indexArray[0]][indexArray[1]];
			var indexArray2 =this.getEdgeS_index(code3);
			
			if(indexArray2[0]==indexLend){//还位
				edgeCodeArray.push({"code":code3,"isH":true});
				//判断是否编完
				if(edgeLend.length!=0){
					//继续借位
					var lend = this.getEdgeLendIndex();
					if(lend==-1)return;
					var jw = edge[lend];
					if(this.edgeIsHoming(jw,lend)){
						return;
					}
					this.handEdgeCodeLend(lend,indexArray2[1]);
				}
			}else{
				this.handReadEdgeCode(indexArray[0],indexArray[1],indexLend);
			}
			
		}
		
	}
	//需要借位的时候取编码逻辑
	this.handEdgeCodeLend = function(indexLend,c){
		if(indexLend==-1){
			return;//借位顺序里的位置全部用完，默认读码结果
		}
		var code = "";
		var code2 = "";
		if(edgeIsKeep){//保持色向借位
			code = edgeS[indexLend][c];
			code2 = edge[indexLend][c];
		}else{
			code = edgeS[indexLend][0];
			code2 = edge[indexLend][0];
		}
		edgeCodeArray.push({"code":code,"isLend":true});
		edgeCodeArray.push({"code":code2});
		
		var deleteIndex = edgeLend.indexOf(this.getEdgeS_index(code2)[0]);
		if(deleteIndex!=-1){
			edgeLend.splice(deleteIndex,1);//编过的位置要在借位顺序里即时删除
		}
		
		var indexArray = this.getEdgeS_index(code2);
		var code3 = edge[indexArray[0]][indexArray[1]];
		var indexArray2 =this.getEdgeS_index(code3);
		
		if(indexArray2[0]==indexLend){//还位
			edgeCodeArray.push({"code":code3,"isH":true});
			//判断是否编完
			if(edgeLend.length!=0){
				//继续借位
				indexLend = this.getEdgeLendIndex();
				if(indexLend==-1)return;
				var jw = edge[indexLend];
				if(this.edgeIsHoming(jw,indexLend)){
					return;
				}
				this.handEdgeCodeLend(indexLend,indexArray2[1]);
			}
		}else{
			this.handReadEdgeCode(indexArray[0],indexArray[1],indexLend);
			
		}
		
	}
	//取出可以借位的位置index
	this.getEdgeLendIndex = function(){
		var indexLend = -1;//当前所借的位置
		do{
			if(edgeLend.length==0){
				break;
			}
			indexLend = edgeLend.shift();//从借位顺序里取出第一个，并删除它
			//如果所借位置已归位，则重新取一个借位位置
			var jw = edge[indexLend];
			var is = this.edgeIsHoming(jw,indexLend);
			if(!is){
				break;
			}
		}while(edgeLend.length>0);
		
		return indexLend;
	}
	//用来判断当前位置是否已经归位
	this.edgeIsHoming = function(c,indexLend){
		var res = false;
		var s = edgeS[indexLend];
		if(c[0]==s[0]){
			//归位且色向正确
			return true;
		}else if(c[0]==s[1]){
			//不是缓冲块的归位
			if(indexLend!=bufferIndex_E){
				var b = edgeCodeFlipArray.includes(s[1]+""+s[0]);
				if(!b){
					edgeCodeFlipArray.push(s[1]+""+s[0]);
				}
			}
			return true;
		}
		
		return res;
	}
	/*-----------棱读码end-----------*/
	
	/**------编码反推start------*/
	this.handleCodes = function(cCode,cFs,eCode,eFs,dlzb){
		
		var flag = false;
		var title = "";
		var scramble = "";
		
		
		var jioC = "";
		var jioE = "";
		if(cCode.length%2!=0){
			jioC = cCode[cCode.length-1];
			jioE = eCode[eCode.length-1];
		}
		var c_Code = this.splitTwo(cCode);
		var c_Fs = this.splitTwo(cFs);
		var e_Code = this.splitTwo(eCode);
		var e_Fs = this.splitTwo(eFs);
		
		var cFsRes =this.handleCornerFs(c_Fs);
		if(!cFsRes)return {"flag":true,"title":"角翻色错误"};
		var eFsRes = this.handleEdgeFs(e_Fs);
		if(!eFsRes)return {"flag":true,"title":"棱翻色错误"};
		
		if(jioC!=""){
			var jioArray = this.getCornerS_index(jioC);
			var index = jioArray[1];
			var buffer = corner[bufferIndex_C];
			if(index==0){
				//012 012
				corner[bufferIndex_C]=corner[jioArray[0]];
				corner[jioArray[0]]=buffer;
			}else if(index==1){
				//120 201
				corner[bufferIndex_C]=corner[jioArray[0]][1]+corner[jioArray[0]][2]+corner[jioArray[0]][0];
				corner[jioArray[0]]=buffer[2]+buffer[0]+buffer[1];
			}else{
				//201 120
				corner[bufferIndex_C]=corner[jioArray[0]][2]+corner[jioArray[0]][0]+corner[jioArray[0]][1];
				corner[jioArray[0]]=buffer[1]+buffer[2]+buffer[0];
			}
			
			var jioArrayE = this.getEdgeS_index(jioE);
			var indexE = jioArrayE[1];
			var bufferE = edge[bufferIndex_E];
			if(indexE==0){
				edge[bufferIndex_E] = edge[jioArrayE[0]];
				edge[jioArrayE[0]] = bufferE;
			}else{
				edge[bufferIndex_E] = edge[jioArrayE[0]][1]+edge[jioArrayE[0]][0];
				edge[jioArrayE[0]] = bufferE[1]+bufferE[0];
			}
			
		}
		
		c_Code = this.reverse(c_Code);
		e_Code =this.reverse(e_Code);
		
		
		var r1 = this.handCornerCode(c_Code);
		if(!r1)return {"flag":true,"title":"角编码错误"};
		var r2 = this.handEdgeCode(e_Code);
		if(!r2)return {"flag":true,"title":"棱编码错误"};
		
		
		var step = 21;
		if(cFs.length>=10&&eFs.length>10){
			step = 22;
		}
		
		var scramble = "";
		if(dlzb==0){//打乱坐标任意
			dlzb=1;
			var rot = Math.floor(Math.random() * 24);
			if(rot==1){
				dlzb=0;
			}
		}
		if(dlzb==1){
			var coordinate = [["Uw' y", "Uw"],["Uw y'", "Uw'"],["Uw2 y2'", "Uw2"],["Rw' x", "Rw"],["Rw x'", "Rw'"],["Rw2 x2'", "Rw2"],
			["Fw' z", "Fw"],["Fw z'", "Fw'"],["Fw z' Rw' x", "Rw Uw'"],["Fw' z Rw' x", "Rw Uw"],["Fw2 z2 Rw' x", "Rw Uw2"],
			["Bw z Rw x'", "Rw' Uw'"],["Bw' z' Rw x'", "Rw' Uw"],["Bw2 z2 Rw x'", "Rw' Uw2"],["Dw2 y2 Rw2 x2", "Rw2 Uw2"],
			["Lw' x'  Fw' z", "Fw Uw"],["Lw x  Fw' z", "Fw Uw'"],["Lw2 x2  Fw' z", "Fw Uw2"],["Rw' x Fw z'", "Fw' Uw"],["Rw x' Fw z'", "Fw' Uw'"],["Rw2 x2 Fw z'", "Fw' Uw2"]
			];
			var s = this.getState();
			var rot = Math.floor(Math.random() * coordinate.length);
			var rot0 = coordinate[rot][0];
			var rot1 = coordinate[rot][1];
			var res = getScrambleForm(rot0);
			this.disrupt(res);
			var state = this.getState();
			scramble = min2phase.getScramble(state,step);
			scramble = scramble+coordinate[rot][1];
		}else{
			var state = this.getState();
			scramble = min2phase.getScramble(state,step);
		}
		
		return {"flag":flag,"scramble":scramble};
	}
	
	this.handCornerCode = function(c_Code){
		var is = true;
		for(var i=0;i<c_Code.length;i++){
			var code1=c_Code[i][0];
			var code2=c_Code[i][1];
			if(this.isSameCorner(code1,code2)){
				is = false;
				break;
			}
			
			var array1 = this.getCornerS_index(code1);
			var array2 = this.getCornerS_index(code2);
			var index1 = array1[1];
			var index2 = array2[1];
			
			var buffer = corner[bufferIndex_C];
			var c1 = corner[array1[0]];
			var c2 = corner[array2[0]];
			if(index1==0&&index2==0){
				corner[bufferIndex_C] = c2;
				corner[array1[0]] = buffer;
				corner[array2[0]] = c1;
			}else if(index1==0&&index2==1){
				corner[bufferIndex_C] = c2[1]+c2[2]+c2[0];
				corner[array1[0]] = buffer[0]+buffer[1]+buffer[2];
				corner[array2[0]] = c1[2]+c1[0]+c1[1];
			}else if(index1==0&&index2==2){
				corner[bufferIndex_C] = c2[2]+c2[0]+c2[1];
				corner[array1[0]] = buffer[0]+buffer[1]+buffer[2];
				corner[array2[0]] = c1[1]+c1[2]+c1[0];
			}else if(index1==1&&index2==0){
				corner[bufferIndex_C] = c2[0]+c2[1]+c2[2];
				corner[array1[0]] = buffer[2]+buffer[0]+buffer[1];
				corner[array2[0]] = c1[1]+c1[2]+c1[0];
			}else if(index1==1&&index2==1){
				corner[bufferIndex_C] = c2[1]+c2[2]+c2[0];
				corner[array1[0]] = buffer[2]+buffer[0]+buffer[1];
				corner[array2[0]] = c1[0]+c1[1]+c1[2];
			}else if(index1==1&&index2==2){
				corner[bufferIndex_C] = c2[2]+c2[0]+c2[1];
				corner[array1[0]] = buffer[2]+buffer[0]+buffer[1];
				corner[array2[0]] = c1[2]+c1[0]+c1[1];
			}else if(index1==2&&index2==0){
				corner[bufferIndex_C] = c2[0]+c2[1]+c2[2];
				corner[array1[0]] = buffer[1]+buffer[2]+buffer[0];
				corner[array2[0]] = c1[2]+c1[0]+c1[1];
			}else if(index1==2&&index2==1){
				corner[bufferIndex_C] = c2[1]+c2[2]+c2[0];
				corner[array1[0]] = buffer[1]+buffer[2]+buffer[0];
				corner[array2[0]] = c1[1]+c1[2]+c1[0];
			}else if(index1==2&&index2==2){
				corner[bufferIndex_C] = c2[2]+c2[0]+c2[1];
				corner[array1[0]] = buffer[1]+buffer[2]+buffer[0];
				corner[array2[0]] = c1[0]+c1[1]+c1[2];
			}
			
		}
		return is;
	}
	
	this.handEdgeCode = function(e_Code){
		var is = true;
		for(var i=0;i<e_Code.length;i++){
			var code1=e_Code[i][0];
			var code2=e_Code[i][1];
			if(this.isSameEdge(code1,code2)){
				is = false;
				break;
			}
			
			var array1 = this.getEdgeS_index(code1);
			var array2 = this.getEdgeS_index(code2);
			var index1 = array1[1];
			var index2 = array2[1];
			
			var buffer = edge[bufferIndex_E];
			var c1 = edge[array1[0]];
			var c2 = edge[array2[0]];
			
			if(index1==0&&index2==0){
				edge[bufferIndex_E] = c2;
				edge[array1[0]] = buffer;
				edge[array2[0]] = c1;
			}else if(index1==0&&index2==1){
				edge[bufferIndex_E] = c2[1]+c2[0];
				edge[array1[0]] = buffer;
				edge[array2[0]] = c1[1]+c1[0];
			}else if(index1==1&&index2==0){
				edge[bufferIndex_E] = c2;
				edge[array1[0]] = buffer[1]+buffer[0];
				edge[array2[0]] = c1[1]+c1[0];
			}else if(index1==1&&index2==1){
				edge[bufferIndex_E] = c2[1]+c2[0];
				edge[array1[0]] = buffer[1]+buffer[0];
				edge[array2[0]] = c1;
			}
			
			
		}
		
		return is;
	}
	
	this.handleCornerFs = function(c_Fs){
		var res = true;
		var seXiangHe = 0;//色向和，用于校验角翻色是否要搭配缓冲
		for(var i = 0;i<c_Fs.length;i++){
			var fs = c_Fs[i];
			var fs1 = fs[0];
			var fs2 = fs[1];
			if(fs1==fs2){
				continue;
			}
			if(!this.isSameCorner(fs1,fs2)){
				res = false;
				break;
			}
			//只有在相同角块上才能翻色
			var array = this.getCornerS_index(fs1);
			var array2 = this.getCornerS_index(fs2);
			var offset = 3-array[1]-array2[1];
			
			var cIndex1 = array[1];
			var cIndex2 = array2[1];
			var index = array[0];//待翻色角块位置
			
			var res = cIndex1-cIndex2;
			var offset = 0;
			if(res==-1||res==2){
				offset = 1;
				corner[index] = corner[index][1]+corner[index][2]+corner[index][0];
			}else{
				offset = 2;
				corner[index] = corner[index][2]+corner[index][0]+corner[index][1];
			}
			
			
			seXiangHe += offset;
		}
		
		if(!res){
			return res;
		}
		
		switch(seXiangHe % 3){//用缓冲块适配翻色
			case 1:
				corner[bufferIndex_C] = corner[bufferIndex_C][2]+corner[bufferIndex_C][0]+corner[bufferIndex_C][1];
				break;
			case 2:
				corner[bufferIndex_C] = corner[bufferIndex_C][1]+corner[bufferIndex_C][2]+corner[bufferIndex_C][0];
				break;
		}
		
		return res;
	}
	
	
	this.handleEdgeFs = function(e_Fs){
		var res = true;
		var seXiangHe = 0;//色向和，用于校验角翻色是否要搭配缓冲
		for(var i = 0;i<e_Fs.length;i++){
			var fs = e_Fs[i];
			var fs1 = fs[0];
			var fs2 = fs[1];
			if(fs1==fs2){
				continue;
			}
			if(!this.isSameEdge(fs1,fs2)){
				res = false;
				break;
			}
			//只有在相同角块上才能翻色
			var array = this.getEdgeS_index(fs1);
			var index = array[0];//待翻色棱块位置
			edge[index] = edge[index][1]+edge[index][0];
			seXiangHe++;
		}
		if(!res){
			return res;
		}
		if(seXiangHe % 2 ==1){
			edge[bufferIndex_E] = edge[bufferIndex_E][1]+edge[bufferIndex_E][0];
		}
		
		
		return res;
	}
	
	//判断两个角编码是否在同一个块上
	this.isSameCorner = function(c1,c2){
		var is = false;
		var c1Array = this.getCornerS_index(c1);
		var c2Array = this.getCornerS_index(c2);
		if(c1Array[0]==c2Array[0]){
			return true;
		}
		return is;
	}
	
	//判断两个棱编码是否在同一个块上
	this.isSameEdge = function(e1,e2){
		var is = false;
		var e1Array = this.getEdgeS_index(e1);
		var e2Array = this.getEdgeS_index(e2);
		if(e1Array[0]==e2Array[0]){
			return true;
		}
		return is;
	}
	
	//处理数组，令其返回两两合并的数组 例如["C","D","A","F","G","K"],返回["CD","AF","GK"]
	this.splitTwo = function(s){
		var res = [];
		for(var i = 0;i<s.length;i++){
			if(i%2==0){
				if(i<s.length-1){
					var str = s[i]+s[i+1];
					res.push(str);
				}
			}
		}
		console.log(res);
		return res;
	}
	
	//将两两合并的数组倒序 例如["CD","AF","GK"], 返回["KG","FA","DC"]
	this.reverse = function(array){
		var res = [];
		for(var i=array.length-1;i>=0;i--){
			var code = array[i][1]+array[i][0];
			res.push(code);
		}
		return res;
	}

	/**------编码反推end------*/
}

const getScrambleForm = function(scramble){
	var regex = /(([URFBLD])(w?)(['2]?))|([EMSxyz](['2]?))/g;
	var result = scramble.replace(/\s+/g, "");
	var res = result.match(regex);
	return res;
}
	
const getCubeState = function(scramble,cornerS,edgeS){
	var cc = new cube(cornerS,edgeS);
	var res = getScrambleForm(scramble);
	cc.disrupt(res);
	return cc.getState();
}


const readCode = function(scramble,cornerS,edgeS,bufferIndex_C,bufferIndex_E,cornerIsKeep,edgeIsKeep,cornerLend,edgeLend){
	var cc = new cube(cornerS,edgeS);
	var res = getScrambleForm(scramble);
	cc.disrupt(res);
	cc.initRead(bufferIndex_C,bufferIndex_E,cornerIsKeep,edgeIsKeep,cornerLend,edgeLend);
	return cc.read();
}

const getScrambleFromCode = function(cornerS,edgeS,bufferIndex_C,bufferIndex_E,cCode,cFs,eCode,eFs,dlzb){
	var flag = false;
	var title = "error";
	var scramble = "";
	var cc = new cube(cornerS,edgeS);
	cc.initBuffer(bufferIndex_C,bufferIndex_E);
	
	for (var i=0;i<cCode.length;i++) {
		var code = cCode[i];
		if(code==cornerS[bufferIndex_C][0]
			||code==cornerS[bufferIndex_C][1]
			||code==cornerS[bufferIndex_C][2]
		){
			title="角编码错误";
			flag = true;
			break;
		}
	}
	
	if(flag) return {"flag":flag,"title":title};
	
	for (var i=0;i<cFs.length;i++) {
		var code = cFs[i];
		if(code==cornerS[bufferIndex_C][0]
			||code==cornerS[bufferIndex_C][1]
			||code==cornerS[bufferIndex_C][2]
		){
			title="角翻色错误";
			flag = true;
			break;
		}
	}
	if(flag) return {"flag":flag,"title":title};
	
	for (var i=0;i<eCode.length;i++) {
		var code = eCode[i];
		if(code==edgeS[bufferIndex_E][0]
			||code==edgeS[bufferIndex_E][1]
		){
			title="棱编码错误";
			flag = true;
			break;
		}
	}
	if(flag) return {"flag":flag,"title":title};
	
	
	for (var i=0;i<eFs.length;i++) {
		var code = eFs[i];
		if(code==edgeS[bufferIndex_E][0]
			||code==edgeS[bufferIndex_E][1]
		){
			title="棱翻色错误";
			flag = true;
			break;
		}
	}
	if(flag) return {"flag":flag,"title":title};
	
	var res = cc.handleCodes(cCode,cFs,eCode,eFs,dlzb);
	
	return res;
}



export default{
	getCubeState,readCode,getScrambleFromCode
}